package jeudelavie.modele;

import java.util.logging.Level;
import java.util.logging.Logger;

public class Plateau extends Thread implements Runnable{
    private int hauteur, largeur;
    private Cellule tabCellules[][];
    private boolean etatThread;
    
    //Constructeur
    public Plateau(int hauteur, int largeur){
        this.hauteur = hauteur;
        this.largeur = largeur;
        this.etatThread = false;
        
        tabCellules = new Cellule[hauteur][largeur];
        
        for (int i = 0 ; i < hauteur ; i++)
        {
            for (int j = 0 ; j < largeur ; j++)
            {
                tabCellules[i][j] = new Cellule(i,j,0);
            }
        }
    }
    
    //Accesseurs et Mutateurs    
    public Cellule[][]  getTabCellules() {
        return tabCellules;
    }
    
    public Cellule getCellule(int i, int j){
        return tabCellules[i][j];
    }
    
    public int getHauteur() {
        return hauteur;
    }

    public int getLargeur() {
        return largeur;
    }
    public boolean isEtatThread() {
        return etatThread;
    }

    public void setEtatThread(boolean etatThread) {
        this.etatThread = etatThread;
    }

    //Remplit le plateau de cellules
    public void initialiser(int etat){
        for(int i = 0; i < getHauteur(); i++)
        {
            for (int j = 0; j < getLargeur(); j++)
            {
                tabCellules[i][j].setEtatPrecedent(etat);
                tabCellules[i][j].setEtatSuivant(etat);
                tabCellules[i][j].notifierObservateur();
            }
        }        
    }
    
    //Donne à chaque cellule ses voisins
    public void construireVoisinages(){
        for (int i = 0 ; i < getHauteur() ; i++)
        {
            for (int j = 0 ; j < getLargeur() ; j++)
            {
                if(dansLePlateau(i-1,j-1)){tabCellules[i][j].ajouteVoisin(tabCellules[i-1][j-1]);}
                if(dansLePlateau(i-1,j)){tabCellules[i][j].ajouteVoisin(tabCellules[i-1][j]);}
                if(dansLePlateau(i-1,j+1)){tabCellules[i][j].ajouteVoisin(tabCellules[i-1][j+1]);}
                if(dansLePlateau(i,j-1)){tabCellules[i][j].ajouteVoisin(tabCellules[i][j-1]); }
                if(dansLePlateau(i,j+1)){tabCellules[i][j].ajouteVoisin(tabCellules[i][j+1]);}
                if(dansLePlateau(i+1,j-1)){tabCellules[i][j].ajouteVoisin(tabCellules[i+1][j-1]);}
                if(dansLePlateau(i+1,j)){ tabCellules[i][j].ajouteVoisin(tabCellules[i+1][j]);}
                if(dansLePlateau(i+1,j+1)){tabCellules[i][j].ajouteVoisin(tabCellules[i+1][j+1]);}
            }
        }   
    }
    
    //Donne à chaque cellule son nombre de voisins vivants
    public void calculerVoisins(){
        for (int i = 0 ; i < getHauteur() ; i++)
        {
            for (int j = 0 ; j < getLargeur() ; j++)
            {
                tabCellules[i][j].calculerVoisinsVivants();
            }
        }
    }
    
    //Genere aléatoirement une grille de cellules avec proba la probabilité de vie
    public void generationAleatoire(double proba){
        for (int i = 0; i <  getLargeur();  i++)
        {
            for (int j = 0 ; j < getHauteur() ; j++)
            {
                double alea = Math.random();
                if(proba>alea){
                    tabCellules[i][j].setEtatPrecedent(1);
                }
                else{
                    tabCellules[i][j].setEtatPrecedent(0);
                }
                tabCellules[i][j].notifierObservateur();
            }
        }
        
    }
    
    //Passe la grille à la prochaine génération
    public void generationSuivante(){
        
        for (int i = 0; i< getLargeur() ;  i++)
        {
            for (int j = 0 ; j < getHauteur() ; j++)
            {
                tabCellules[i][j].calculerVoisinsVivants();
                tabCellules[i][j].majEtat();
            }
        }
        
        for (int i = 0; i< getHauteur() ;  i++)
        {
            for (int j = 0 ; j < getLargeur() ; j++)
            {
                tabCellules[i][j].switchEtat();
                tabCellules[i][j].notifierObservateur();
            }
        }
    }

    //Vérifie si les cases appartiennent à la grille ou non
    final boolean dansLePlateau(int i, int j){
        if ( (i>=0) &&(i<getHauteur()) &&  (j>=0)&&(j<getLargeur()) )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    //Inverse l'etat d'une cellule
    public void changeEtatCellule(int x, int y) {
        if(tabCellules[x][y].getEtatPrecedent()==1)
        {
            tabCellules[x][y].setEtatSuivant(0);
            tabCellules[x][y].setEtatPrecedent(0);
            tabCellules[x][y].notifierObservateur();
        }
        else
        {
            tabCellules[x][y].setEtatSuivant(1);
            tabCellules[x][y].setEtatPrecedent(1);
            tabCellules[x][y].notifierObservateur();
        }
        
    }
    
    //Change l'état d'une cellule donnée
    public void modifierCellule(int _x, int _y, int _etat) {
        tabCellules[_x][_y].setEtatPrecedent(_etat);
    }
    
    //Fait tourner le modèle
    @Override
    public void run(){
        setEtatThread(true);
        construireVoisinages();
        while(true)
        {            
                try {
                    Thread.sleep(150);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Plateau.class.getName()).log(Level.SEVERE, null, ex);
                }
            if(isEtatThread()==true){
                generationSuivante();
            }
          }
    }

}


